package com.cm.tianwt.socks;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

import javax.net.ServerSocketFactory;

import com.cm.tianwt.socks.service.SocksHandler;
import com.cm.tianwt.socks.service.SocksHandlerManager;
import com.cm.tianwt.socks.utils.Configs;
import com.cm.tianwt.socks.utils.LogUtils;
import com.cm.tianwt.socks.utils.Utils;

public class SocksProxyServer  extends Thread{
	
	private int port;
	private int maxConnectionLength; //最大连接数
	
	private volatile ServerSocket mProxyServerSocket;
	
	public SocksProxyServer( int port, int maxConnectionLength) {
		super();
		this.port = port;
		this.maxConnectionLength = maxConnectionLength;
		
	}
	
	private ServerSocket createSocketServer() throws IOException 
	{
		ServerSocketFactory defaultSocketFactory = ServerSocketFactory.getDefault();
		ServerSocket serverSocket = defaultSocketFactory.createServerSocket(port, maxConnectionLength);
		serverSocket.setReuseAddress(true);
		if(Configs.IS_DEBUG) {
			serverSocket.setSoTimeout(Configs.DEBUG_IDEL_TIMEOUT);
		}else {
			serverSocket.setSoTimeout(Configs.IDEL_TIMEOUT);
		}
		return serverSocket;
	}
	
	
	public SocksProxyServer(int port) {
		this(port,(Runtime.getRuntime().availableProcessors()*2+1)*10);
	}
	
	public int getMaxConnectionLength() {
		return maxConnectionLength;
	}
	
	public int getPort() {
		return port;
	}
	
	
	public void shutDown() {
		Utils.closeQuiety(this.mProxyServerSocket);
		this.mProxyServerSocket = null;
	}
	
	@Override
	public void run() {
		super.run();
		
		synchronized (this) {
			try {
				this.mProxyServerSocket =  createSocketServer();
				if(isReady(this.mProxyServerSocket)) {
					listenOnServerSocket();
				}else {
					LogUtils.E("服务器创建失败！");
				}
			
			}catch (Exception e) {
				e.printStackTrace();
			}finally {
				shutDown();
			}
		}
	}


	private void listenOnServerSocket() throws IOException {
		
		
		while (!isInterrupted() && isReady(this.mProxyServerSocket)) {
				try {
					Socket clientSocket = accept();
					if(clientSocket!=null) {
						startProxyClient(clientSocket);
					}
				} catch (SocketTimeoutException e) {
					e.printStackTrace();
					continue;
				}catch (Exception e) {
					e.printStackTrace();
					throw e;
				}
		}
	}

	private synchronized void  startProxyClient(Socket clientSocket) {
		
		SocksHandler handler = SocksHandlerManager.create(clientSocket);
		if(handler!=null) {
			handler.startService();
		}
		
		
	}

	private Socket accept() throws IOException {
		
		Socket socket = this.mProxyServerSocket.accept();
		socket.setSoTimeout(Configs.READ_TIMEOUT);
		socket.setReuseAddress(true);
		socket.setTcpNoDelay(true);
		
		return socket;
	}

	public static boolean isReady(ServerSocket server) {
		return server!=null && !server.isClosed();
	}
	

}
